package test;

import geometry.Box;
import geometry.Geometry;
import geometry.Sphere;
import grammar.Assembly;
import grammar.Design;
import grammar.InstantiationInput;
import grammar.ModificationRule;
import grammar.Product;
import grammar.Rule;
import graph.GNode;

import java.util.HashMap;
import java.util.Map;

public class Toobeez {
    
    public static String TOP = "TOP";
    public static String BOTTOM = "BOTTOM";
    public static String LEFT = "LEFT";
    public static String RIGHT = "RIGHT";
    public static String FRONT = "FRONT";
    public static String BACK = "BACK";
    public static String NO_BALL = "NO_BALL";
    
    public static Design buildInitialBryce() {
        Design design = new Design();
        Product structure = design.setProduct("STRUCTURE");
        Assembly assembly = design.addAssembly("ASSEMBLY");
        Box pole = design.addBox(assembly,1,10,1,"POLE");
        pole.addLabel(NO_BALL);
        return design;
    }
    
    //Adds a ball on top
    public static Rule addBall() { 
        //LHS XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        Design lhs = new Design();
        Product structure = lhs.setProduct("STRUCTURE");
        Assembly assembly = lhs.addAssembly("ASSEMBLY");
        Box pole = lhs.addBox(assembly,1,10,1,"POLE");
        pole.addLabel(NO_BALL);
        //RHS XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        Design rhs = new Design();
        rhs.setProduct(structure);
        rhs.addAssembly(assembly);
        rhs.addGeometry(assembly,pole);
        Sphere ball = rhs.addSphere(assembly,2,"BALL");
        ball.translateBy(.5, 12, .5);
        
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        InstantiationInput input = new InstantiationInput();
        
        Rule rule = new ModificationRule(lhs, rhs, input, new GNode[]{});
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        Map <Geometry, String[]> labelsToRemove = new HashMap<Geometry, String[]>();
        Map <Geometry, String[]> labelsToAdd = new HashMap<Geometry, String[]>();
        labelsToAdd.put(ball,new String[]{TOP, LEFT, RIGHT, FRONT, BACK, BOTTOM});
        labelsToRemove.put(pole, new String[]{NO_BALL});
        rule.setLabelChanges(labelsToRemove, labelsToAdd);
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        //Input variables
        return rule;    
    }
    
    //Add pole on top
    public static Rule addTopPole() {
        //LHS XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        Design lhs = new Design();
        Product structure = lhs.setProduct("STRUCTURE");
        Assembly assembly = lhs.addAssembly("ASSEMBLY");
        Sphere ball = lhs.addSphere(assembly,2,"BALL");
        ball.addLabel(TOP);
        //RHS XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        Design rhs = new Design();
        rhs.setProduct(structure);
        rhs.addAssembly(assembly);
        rhs.addGeometry(assembly,ball);
        Box pole = rhs.addBox(assembly,1,10,1,"POLE");
        pole.translateBy(-.5, 2, -.5);
        pole.addLabel(NO_BALL);
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        InstantiationInput input = new InstantiationInput();
        
        Rule rule = new ModificationRule(lhs, rhs, input, new GNode[]{});
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        Map <Geometry, String[]> labelsToRemove = new HashMap<Geometry, String[]>();
        Map <Geometry, String[]> labelsToAdd = new HashMap<Geometry, String[]>();
        labelsToRemove.put(ball, new String[]{TOP});
        rule.setLabelChanges(labelsToRemove, labelsToAdd);
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        //Input variables
        return rule;    
    }

    //Add pole to the left
    public static Rule addLeftPole() {
        //LHS XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        Design lhs = new Design();
        Product structure = lhs.setProduct("STRUCTURE");
        Assembly assembly = lhs.addAssembly("ASSEMBLY");
        Sphere ball = lhs.addSphere(assembly,2,"BALL");
        ball.addLabel(LEFT);
        //RHS XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        Design rhs = new Design();
        rhs.setProduct(structure);
        rhs.addAssembly(assembly);
        rhs.addGeometry(assembly,ball);
        Box pole = rhs.addBox(assembly,1,10,1,"POLE");
        pole.addLabel(NO_BALL);
        pole.rotate(0, 0, 90);
        pole.translateBy(-2, -.5, -.5);
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        InstantiationInput input = new InstantiationInput();
        
        Rule rule = new ModificationRule(lhs, rhs, input, new GNode[]{});
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        Map <Geometry, String[]> labelsToRemove = new HashMap<Geometry, String[]>();
        Map <Geometry, String[]> labelsToAdd = new HashMap<Geometry, String[]>();
        labelsToRemove.put(ball, new String[]{LEFT});
        rule.setLabelChanges(labelsToRemove, labelsToAdd);
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        //Input variables
        return rule;    
    }

    //Add pole to the front
    public static Rule addFrontPole() {
        //LHS XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        Design lhs = new Design();
        Product structure = lhs.setProduct("STRUCTURE");
        Assembly assembly = lhs.addAssembly("ASSEMBLY");
        Sphere ball = lhs.addSphere(assembly,2,"BALL");
        ball.addLabel(FRONT);
        //RHS XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        Design rhs = new Design();
        rhs.setProduct(structure);
        rhs.addAssembly(assembly);
        rhs.addGeometry(assembly,ball);
        Box pole = rhs.addBox(assembly,1,10,1,"POLE");
        pole.rotate(90, 0, 0);
        pole.translateBy(-.5, .5, 2);
        pole.addLabel(NO_BALL);
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        InstantiationInput input = new InstantiationInput();
        
        Rule rule = new ModificationRule(lhs, rhs, input, new GNode[]{});
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        Map <Geometry, String[]> labelsToRemove = new HashMap<Geometry, String[]>();
        Map <Geometry, String[]> labelsToAdd = new HashMap<Geometry, String[]>();
        labelsToRemove.put(ball, new String[]{FRONT});
        rule.setLabelChanges(labelsToRemove, labelsToAdd);
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        
        //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        //Input variables
        return rule;    
    }


}
